From a5f8a74ec1d7390c81f4cbae9b84ca942b879233 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 27 Dec 2016 00:18:52 +0100 Subject: [PATCH] vulkan: Only render minimal region It's faster to render once for every rectangle in the clip region than rendering the outline of the clip region. Especially because this reduces the time necessary to build up the frame data. In widget-factory (where we have 3 rectangles), this leads to a 5x speedup in the rendering time rendering alone. Snapshotting time goes from 10ms to ~1ms, which is another huge improvement. --- gsk/gskvulkanrender.c | 88 ++++++++++++++++++++++------------------- gsk/gskvulkanrenderer.c | 16 +------- 2 files changed, 49 insertions(+), 55 deletions(-) diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index a2968cc11e..12dac4d73f 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -26,7 +26,7 @@ struct _GskVulkanRender graphene_matrix_t mvp; int scale_factor; VkRect2D viewport; - VkRect2D scissor; + cairo_region_t *clip; GHashTable *framebuffers; GskVulkanCommandPool *command_pool; @@ -49,32 +49,31 @@ struct _GskVulkanRender }; static void -gsk_vulkan_render_compute_mvp (GskVulkanRender *self, - const graphene_rect_t *rect) +gsk_vulkan_render_setup (GskVulkanRender *self, + GskVulkanImage *target, + const graphene_rect_t *rect) { GdkWindow *window = gsk_renderer_get_window (self->renderer); graphene_matrix_t modelview, projection; - cairo_rectangle_int_t extents; + + self->target = g_object_ref (target); if (rect) { - self->scissor = (VkRect2D) { { 0, 0 }, { rect->size.width, rect->size.height } }; self->viewport = (VkRect2D) { { rect->origin.x, rect->origin.y }, { rect->size.width, rect->size.height } }; self->scale_factor = 1; + self->clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { + 0, 0, + gsk_vulkan_image_get_width (target), gsk_vulkan_image_get_height (target) + }); } else { - cairo_region_get_extents (gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (self->renderer)), - &extents); - self->scale_factor = gsk_renderer_get_scale_factor (self->renderer); self->viewport.offset = (VkOffset2D) { 0, 0 }; self->viewport.extent.width = gdk_window_get_width (window) * self->scale_factor; self->viewport.extent.height = gdk_window_get_height (window) * self->scale_factor; - self->scissor.offset.x = extents.x * self->scale_factor; - self->scissor.offset.y = extents.y * self->scale_factor; - self->scissor.extent.width = extents.width * self->scale_factor; - self->scissor.extent.height = extents.height * self->scale_factor; + self->clip = gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (self->renderer)); } graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0); @@ -464,6 +463,7 @@ gsk_vulkan_render_draw (GskVulkanRender *self, GskVulkanBuffer *buffer; VkCommandBuffer command_buffer; GSList *l; + guint i; gsk_vulkan_render_prepare_descriptor_sets (self, sampler); @@ -483,36 +483,43 @@ gsk_vulkan_render_draw (GskVulkanRender *self, .maxDepth = 1 }); - vkCmdSetScissor (command_buffer, - 0, - 1, - &self->scissor); - - vkCmdBeginRenderPass (command_buffer, - &(VkRenderPassBeginInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = self->render_pass, - .framebuffer = gsk_vulkan_render_get_framebuffer (self, self->target), - .renderArea = { - { 0, 0 }, - { - gsk_vulkan_image_get_width (self->target), - gsk_vulkan_image_get_height (self->target) + for (i = 0; i < cairo_region_num_rectangles (self->clip); i++) + { + cairo_rectangle_int_t rect; + + cairo_region_get_rectangle (self->clip, i, &rect); + + vkCmdSetScissor (command_buffer, + 0, + 1, + &(VkRect2D) { + { rect.x * self->scale_factor, rect.y * self->scale_factor }, + { rect.width * self->scale_factor, rect.height * self->scale_factor } + }); + + vkCmdBeginRenderPass (command_buffer, + &(VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = self->render_pass, + .framebuffer = gsk_vulkan_render_get_framebuffer (self, self->target), + .renderArea = { + { rect.x * self->scale_factor, rect.y * self->scale_factor }, + { rect.width * self->scale_factor, rect.height * self->scale_factor } + }, + .clearValueCount = 1, + .pClearValues = (VkClearValue [1]) { + { .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } } } }, - .clearValueCount = 1, - .pClearValues = (VkClearValue [1]) { - { .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } } - } - }, - VK_SUBPASS_CONTENTS_INLINE); + VK_SUBPASS_CONTENTS_INLINE); - for (l = self->render_passes; l; l = l->next) - { - gsk_vulkan_render_pass_draw (l->data, self, buffer, self->layout, command_buffer); - } + for (l = self->render_passes; l; l = l->next) + { + gsk_vulkan_render_pass_draw (l->data, self, buffer, self->layout, command_buffer); + } - vkCmdEndRenderPass (command_buffer); + vkCmdEndRenderPass (command_buffer); + } gsk_vulkan_command_pool_submit_buffer (self->command_pool, command_buffer, self->fence); @@ -563,6 +570,7 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self) g_slist_free_full (self->cleanup_images, g_object_unref); self->cleanup_images = NULL; + g_clear_pointer (&self->clip, cairo_region_destroy); g_clear_object (&self->target); } @@ -631,9 +639,7 @@ gsk_vulkan_render_reset (GskVulkanRender *self, { gsk_vulkan_render_cleanup (self); - self->target = g_object_ref (target); - - gsk_vulkan_render_compute_mvp (self, rect); + gsk_vulkan_render_setup (self, target, rect); } GskRenderer * diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index 747ed09c90..4ae0f4deee 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -257,23 +257,11 @@ gsk_vulkan_renderer_begin_draw_frame (GskRenderer *renderer, const cairo_region_t *region) { GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer); - cairo_region_t *whole_window; GdkDrawingContext *result; - GdkWindow *window; - - window = gsk_renderer_get_window (renderer); - - whole_window = cairo_region_create_rectangle (&(GdkRectangle) { - 0, 0, - gdk_window_get_width (window), - gdk_window_get_height (window) - }); - result = gdk_window_begin_draw_frame (window, + result = gdk_window_begin_draw_frame (gsk_renderer_get_window (renderer), GDK_DRAW_CONTEXT (self->vulkan), - whole_window); - - cairo_region_destroy (whole_window); + region); return result; } -- 2.30.2